package com.topvision.jack.camerasdk2.camera;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.util.Log;
import android.view.SurfaceHolder;

import com.topvision.jack.camerasdk2.camera.utils.FileUtils;
import com.topvision.jack.camerasdk2.camera.utils.Mp4ParseUtil;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

/**
 * 录制视频实现类
 * 创建时间:2017/12/20
 * 作者 jack
 * 描述
 */
public class VideoRecorder implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {

    private static VideoRecorder instance;
    public final String TAG = VideoRecorder.class.getSimpleName();
    //临时文件有1个,结束录制时,则需要进行合并
    public final int VIDEO_SIZE = 1;
    //录制视频相关API
    private MediaRecorder mMediaRecorder;
    private AudioManager mAudioManager = null;
    //需要合并的视频文件路径
    ArrayList<String> mergeVideos;
    //文件输出地址
    String outputFile;
    //分辨率
    int resolution;
    Context context;
    SurfaceHolder surfaceHolder;
    //记录开始录制时间,视频录制起码1秒以后允许用户进行暂停或结束录制
    long startRecordTime = 0;

    private VideoRecorder() {

    }

    public static VideoRecorder getInstance() {
        if (instance == null) {
            synchronized (VideoRecorder.class) {
                if (instance == null) {
                    instance = new VideoRecorder();
                }
            }
        }
        return instance;
    }


    public boolean prepareVideoRecorder(Context context, Camera mCamera, SurfaceHolder surfaceHolder, String outputFile, int resolution) {
        this.outputFile = outputFile;
        this.resolution = resolution;
        this.context = context;
        this.surfaceHolder = surfaceHolder;

        CamcorderProfile mProfile = CamcorderProfile.get(resolution);
        if (mMediaRecorder == null) {
            mMediaRecorder = new MediaRecorder();
            mMediaRecorder.setOnErrorListener(this);
        } else {
            mMediaRecorder.reset();
        }
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mCamera.unlock();

        mMediaRecorder.setCamera(mCamera);

        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

        mMediaRecorder.setOutputFormat(mProfile.fileFormat); // 设置视频的输出格式
        mMediaRecorder.setAudioEncoder(mProfile.audioCodec); // 设置音频的编码格式
        mMediaRecorder.setVideoEncoder(mProfile.videoCodec); // 设置视频的编码格式
//        FileUtils.createFolder(context, outputFile);
        mMediaRecorder.setOutputFile(new File(outputFile).toString());
        mMediaRecorder.setVideoSize(mProfile.videoFrameWidth,
                mProfile.videoFrameHeight);
        mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);
        // int bitRate = mProfile.videoFrameWidth * mProfile.videoFrameHeight;
        mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate);
        mMediaRecorder.setAudioEncodingBitRate(mProfile.audioBitRate);
        //3078000
        mMediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
        try {
            mMediaRecorder.prepare();
        } catch (Exception e) {
            Log.e(TAG, "Exception preparing MediaRecorder: " + e.getMessage());
            releaseMediaRecorder(mCamera);
            return false;
        }

        return true;
    }


    /**
     * 释放资源
     */
    private void releaseMediaRecorder(Camera mCamera) {
        if (mMediaRecorder != null) {
            try {
                // 加了这段就不会报错
                mMediaRecorder.setOnErrorListener(null);
                mMediaRecorder.setPreviewDisplay(null);
                mMediaRecorder.stop();
                mMediaRecorder.reset();
                mMediaRecorder.release();
                mMediaRecorder = null;
                if (mCamera != null) {
                    mCamera.lock();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }


    @Override
    public void onError(MediaRecorder mediaRecorder, int what, int extra) {
        Log.e(TAG, "what=" + what + "extra=" + extra);
    }


    /**
     * 开始录制
     * 创建时间:2017/12/20
     * 作者 jack
     * 描述 如果佩戴了蓝牙耳机,则声音入口是蓝牙耳机录入
     */
    public void startRecord(Context context) {
        if (mergeVideos == null) {
            mergeVideos = new ArrayList<>();
        }
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        //检查是否A2DP蓝牙耳机音频路由是打开或关闭
        if (!mAudioManager.isBluetoothA2dpOn()) {
            try {
                mMediaRecorder.start();
                startRecordTime = System.currentTimeMillis();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;
        }
        if (!mAudioManager.isBluetoothScoAvailableOffCall()) {
            return;
        }
        startRecordByAirBlue(context);
    }


    /**
     * 停止录制
     *
     * @param mCamera
     */
    public void stopRecord(Camera mCamera) {
        //MediaRecord 有Bug,至少录制1S以上才允许关闭,否则会出现异常
        if (System.currentTimeMillis() - startRecordTime >= 1000) {
            releaseMediaRecorder(mCamera);
            if (mAudioManager.isBluetoothScoOn()) {
                mAudioManager.setBluetoothScoOn(false);
                mAudioManager.stopBluetoothSco();
            }
            //录制结束将最后一个录制视频的文件名称存入合并视频中
            if (mergeVideos.size() >= VIDEO_SIZE) {
                String newPath = FileUtils.renameFile(outputFile);
                mergeVideos.add(newPath);
                mergeVideoFile();
            }
            mergeVideos.clear();
            mergeVideos = null;
        }
    }


    public void pauseRecord(Camera mCamera) {
        releaseMediaRecorder(mCamera);
        if (mAudioManager.isBluetoothScoOn()) {
            mAudioManager.setBluetoothScoOn(false);
            mAudioManager.stopBluetoothSco();
        }
    }

    /**
     * 通过蓝牙耳机进行视频录制
     * 创建时间:2017/12/20
     * 作者 jack
     * 描述
     */
    public void startRecordByAirBlue(Context context) {
        // 蓝牙录音的关键，启动SCO连接，耳机话筒才起作用
        mAudioManager.startBluetoothSco();
        // 蓝牙SCO连接建立需要时间，连接建立后会发出ACTION_SCO_AUDIO_STATE_CHANGED消息，通过接收该消息而进入后续逻辑。
        // 也有可能此时SCO已经建立，则不会收到上述消息，可以startBluetoothSco()前先stopBluetoothSco()
        context.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                int state = intent.getIntExtra(
                        AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
                if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
                    mAudioManager.setBluetoothScoOn(true); // 打开SCO
                    mAudioManager.adjustVolume(AudioManager.ADJUST_RAISE, 0);
                    if (mAudioManager.isBluetoothScoOn()) {
                        mMediaRecorder.start();
                        context.unregisterReceiver(this); // 别遗漏
                    }
                } else {// 等待一秒后再尝试启动SCO
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mAudioManager.startBluetoothSco();
                }

            }
        }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
    }


    /**
     * 暂停录制
     * 创建时间:2017/12/22
     * 作者 jack
     * 描述
     */
    public void pauseRecord(Camera mCamera, String outputPath) {
        if (mMediaRecorder != null) {
            pauseRecord(mCamera);
            //重新命名当前录制视频文件名称
            String newPath = FileUtils.renameFile(outputPath);
            mergeVideos.add(newPath);
        }
    }


    public void resumeRecord(Camera mCamera) {
        if (prepareVideoRecorder(context, mCamera, surfaceHolder, outputFile, resolution)) {
            startRecord(context);
        }
    }

    /**
     * 合并暂停文件
     * 创建时间:2017/12/22
     * 作者 jack
     * 描述
     */
    private void mergeVideoFile() {
        //自定义视频拼接类
        try {
            Mp4ParseUtil.appendMp4List(mergeVideos, outputFile);
            //刪除临时视频文件
            for (String videoPath : mergeVideos) {
                File file = new File(videoPath);
                file.delete();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onInfo(MediaRecorder mediaRecorder, int i, int i1) {

    }
}
